/*
 * Copyright (c) 2010 CCX(China) Co.,Ltd. All Rights Reserved.
 *
 * This software is the confidential and proprietary information of
 * CCX(China) Co.,Ltd. ("Confidential Information").
 * It may not be copied or reproduced in any manner without the express 
 * written permission of CCX(China) Co.,Ltd.
 *
 * Author: zhnb
 * Date: 2011-4-21 下午02:09:38
 */

package com.ccx.memc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.math.BigDecimal;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ccx.dbpool.BoneCPs;
import com.util.ConstUtil;

/**
 * 数据库查询工具类
 * 
 */
public class QueryUtil {

    /**
     * 查询给定的SQL
     * 
     * @param sqlStr
     *            SQL语句
     * @param dataSource
     *            数据源名称（null时，取默认ConstUtil.JYDB_ORACLE）
     * @return 查询结果序列
     */
    public String query(String sqlStr, String dataSource) {

        // 查询结果序列
        String resultStr = null;
        Connection conn = null;
        try {

            conn = this.getConn(dataSource);

            PreparedStatement pst = conn.prepareStatement(sqlStr);

            ResultSet rs = pst.executeQuery();
            while (rs.next()) {
                ResultSetMetaData metaData = rs.getMetaData();
                // 如果返回的值为日期类型（库中为各种DATE），则先转为字符串再返回。
                if ("DATE".equalsIgnoreCase(metaData.getColumnTypeName(1))) {
                    resultStr = this.convertDateToString(rs.getDate(1),
                            ConstUtil.PATTERN_DATE_SHORT);
                }
                // 如果返回值为整型（库中为INTEGER），则选转为字符串，再返回。
                else if ("INTEGER".equalsIgnoreCase(metaData
                        .getColumnTypeName(1))) {
                    resultStr = "" + rs.getInt(1);
                }
                // 如果返回值为数值（库中为NUMBER），则选转为字符串，再返回。
                else if ("NUMBER".equalsIgnoreCase(metaData
                        .getColumnTypeName(1))) {
                    resultStr = this.convertBigDecimalToString(rs
                            .getBigDecimal(1),
                            ConstUtil.NUMBER_BIG_SCALE_MIDDLE);
                }
                // 如果返回值为CLOB，则用CLOB方式读取
                else if ("CLOB".equalsIgnoreCase(metaData.getColumnTypeName(1))) {
                    resultStr = this.convertClobToString(rs.getClob(1));
                }
                // 否则直接获取字符串
                else {
                    resultStr = rs.getString(1);
                }
                // TODO: 1_query：其他类型处理稍后需要添加。
            }

            pst.close();
            rs.close();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            this.closeConn(conn);
        }

        return resultStr;
    }

    /**
     * 查询给定的SQL
     * 
     * @param sqlStr
     *            SQL语句
     * @param dataSource
     *            数据源名称（null时，取默认ConstUtil.JYDB_ORACLE）
     * @return 查询结果序列 List<Map<> >
     */
    @SuppressWarnings("unchecked")
    public List queryList(String sqlStr, String dataSource) {

        // 查询结果序列
        List resultList = new ArrayList();
        Connection conn = null;
        try {

            conn = this.getConn(dataSource);

            PreparedStatement pst = conn.prepareStatement(sqlStr);

            ResultSet rs = pst.executeQuery();
            ResultSetMetaData metaData = rs.getMetaData();

            // 获取字段名数组
            int len = metaData.getColumnCount();
            String[] columnNameArr = new String[len];
            for (int i = 0; i < len; i++) {
                columnNameArr[i] = metaData.getColumnName(i+1);
            }
            //循环填充待返回的结果集
            while (rs.next()) {
                Map map = new HashMap();
                for (int i = 0; i < len; i++) {
                    map.put(columnNameArr[i], rs.getObject(columnNameArr[i]));
                }
                resultList.add(map);

            }

            pst.close();
            rs.close();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            this.closeConn(conn);
        }

        return resultList;
    }

    /**
     * 获取数据库连接
     * 
     * @param dataSource
     *            数据源名称（null时，取默认ConstUtil.JYDB_ORACLE）
     * @return 数据库连接
     */
    private Connection getConn(String dataSource) {
        // 如果未指定数据源，则取默认ConstUtil.JYDB_ORACLE数据源
        if (dataSource == null || dataSource.isEmpty()) {
            return BoneCPs.getConnection(ConstUtil.JYDB_ORACLE);
        }
        // 如果指定数据源，取指定数据源
        return BoneCPs.getConnection(dataSource);
    }

    /**
     * 将Clob转为String （本类私用）
     * 
     * @param clob
     *            大数据Clob对象
     * @return 内容序列
     */
    private String convertClobToString(Clob clob) {

        // 大数据对象为NULL，直接返回NULL
        if (clob == null) {
            return null;
        }

        Reader reader = null;
        BufferedReader buffR = null;

        // 保存按行读入的数据
        StringBuffer strBuff = new StringBuffer();
        try {

            reader = clob.getCharacterStream();
            buffR = new BufferedReader(reader);

            // 保存每次读入的数据行
            String strLine = buffR.readLine();
            while (strLine != null) {
                strBuff.append(strLine);
                strLine = buffR.readLine();
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                if (buffR != null) {
                    buffR.close();
                }
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return strBuff.toString();
    }

    /**
     * 将BigDecimal转为String （本类私用）
     * 
     * @param date
     *            BigDecimal
     * @param fraction
     *            小数位数
     * @return 字符串
     */
    private String convertBigDecimalToString(BigDecimal big, int fraction) {
        // 如果为空，直接返回NULL
        if (big == null) {
            return null;
        }
        // 格式化工具，保留4位小数
        NumberFormat nf = NumberFormat.getInstance();
        nf.setMinimumFractionDigits(fraction);
        nf.setMaximumFractionDigits(fraction);
        // 不使用千分位分割
        nf.setGroupingUsed(false);

        return nf.format(big);
    }

    /**
     * 将sql.Date转为String （本类私用）
     * 
     * @param date
     *            日期（sql.Date）
     * @param pattern
     *            格式化规则
     * @return 日期（String）
     */
    private String convertDateToString(Date date, String pattern) {
        if (date == null) {
            return null;
        }
        String aStrngVar = null;
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        try {
            aStrngVar = sdf.format(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return aStrngVar;
    }

    /**
     * 释放conn占有权
     */
    private void closeConn(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
